// Copyright 2012 dmitry.a.novikov@gmail.com
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "consistenz.h"
#include "variant.h"
#include <new>

namespace CnsZ {

  bool Variant::operator < (const Variant& op2) const {
    if(typ < op2.typ) {
      return true;
    }
    if(typ > op2.typ) {
      return false;
    }
#undef CNSZ_VARIANT
#define CNSZ_VARIANT(Type, ref) \
    case Var##Type##:\
      return as##Type##() < op2.as##Type##();
#undef CNSZ_VAR_OBJ
#define CNSZ_VAR_OBJ(Type, ref) \
    case Var##Type##:\
      return as##Type##() < op2.as##Type##();

    switch(typ) {
    CNSZ_VARIANT_TYPES()
    }
    return false;
  }

  bool Variant::operator > (const Variant& op2) const {
#undef CNSZ_VARIANT
#define CNSZ_VARIANT(Type, ref)
#undef CNSZ_VAR_OBJ
#define CNSZ_VAR_OBJ(Type, ref) \
    case Var##Type##:\
      return as##Type##() > op2.as##Type##();\

    switch(typ) {
    CNSZ_VARIANT_TYPES()
    }
    return false;
  }
  
  bool Variant::operator ==(const Variant& op2) const {
#undef CNSZ_VARIANT
#define CNSZ_VARIANT(Type, ref)
#undef CNSZ_VAR_OBJ
#define CNSZ_VAR_OBJ(Type, ref) \
    case Var##Type##:\
      return as##Type##() == op2.as##Type##();\

    switch(typ) {
    CNSZ_VARIANT_TYPES()
    }
    return false;
  }

#undef CNSZ_VARIANT
#define CNSZ_VARIANT(Type, ref) \
  void Variant::set(ref val) { destruct(); }\
  ref Variant::as##Type##() const {}\
  bool Variant::operator == (ref val) {}

#undef CNSZ_VAR_MAP
#define CNSZ_VAR_MAP(Type, ref) CNSZ_VARIANT(Type, ref)

  void Variant::destructValue() {
#undef CNSZ_VARIANT
#define CNSZ_VARIANT(Type, ref)
#undef CNSZ_VAR_OBJ
#define CNSZ_VAR_OBJ(Type, ref) \
    case Var##Type##:\
      ((Type*)data)->~Type();\
      break;

    switch(typ) {
    CNSZ_VARIANT_TYPES()
    }
  }

  void Variant::constructValue() {
#undef CNSZ_VARIANT
#define CNSZ_VARIANT(Type, ref)
#undef CNSZ_VAR_OBJ
#define CNSZ_VAR_OBJ(Type, ref) \
    case Var##Type##:\
      new (data) Type;\
      break;

    switch(typ) {
    CNSZ_VARIANT_TYPES()
    }
  }
}
